/**
 * \file kernel/main.c
 * \author Davide Gessa
 * \date 10-12-09
 */
#include <main.h>
#include <video.h>
#include <arch.h>
#include <types.h>
#include <syscall.h>
#include <task/task.h>
#include <mm.h>
#include <debug.h>
#include <util.h>
#include <driver.h>

/**
 * Carica il sistema
 *
 * \param mb puntatore al multiboot header
 */
int main(multiboot_info_t *mb)
{
	#ifdef DEBUG
		debug_init();
		#ifdef DEBUG_REG_TRAC
			debug_reg_trace(1);
		#endif
	#endif
	
	DEBUGP("main()\n");
	
	video_set_color(VIDEO_HI_WHITE_BLACK);
	
	// Inizializza le cose necessarie
	video_clear();
	video_puts_colored(VIDEO_HI_BLUE_BLACK, "-> ");
	video_puts_colored(VIDEO_HI_BLUE_BLACK, "Welcome to my microkernel ");
	video_puts_colored(VIDEO_HI_BLUE_BLACK, VER);
	video_puts("\n");
	
	// Arch based
	video_puts_colored(VIDEO_HI_BLUE_BLACK, " -> ");
	video_puts("Initializing Arch ");
	arch_init();
	video_puts("'");
	video_puts(ARCH);
	video_puts("'\n");
	
	// Memory manager
	video_puts_colored(VIDEO_HI_BLUE_BLACK, " -> ");
	video_puts("Starting Memory Manager "); 
	mm_init(mb->mem_lower, mb->mem_upper);
	video_puts("(");
	video_putint((mm_get_total_mem() / 1024));
	video_puts("mb)\n");
	
	// Driver manager
	video_puts_colored(VIDEO_HI_BLUE_BLACK, " -> ");
	video_puts("Starting Driver Manager\n"); 
	driver_init();
		
	// Syscalls
	video_puts_colored(VIDEO_HI_BLUE_BLACK, " -> ");
	video_puts("Starting Syscalls\n");
	syscall_init();

	// Task Manager
	video_puts_colored(VIDEO_HI_BLUE_BLACK, " -> ");
	video_puts("Starting Task Manager\n");	
	task_init(TASK_SWITCH_ROUND_ROBIN);	
	
	//syscall_call(HW_SHUTDOWN, 0, 0, 0);
	//show_task_list();
	char *asd[] = { "task1\0", "lol\0" };
	char *asd2[] = { "task2\0", "lol\0" };
	task_exec(task1, asd, 2);
	task_exec(task2, asd2, 2);
	
	show_task_list();

	service_create("vfs");
	service_create("gui");
	show_service_list();
	show_used_memory();
	
	mm_test();
	while(1);

	
	// Spegnimento se init viene chiuso
	shutdown();
	
	while(1);
}


/**
 * Spegnimento del pc
 */
void shutdown()
{	
	DEBUGP("shutdown()\n");
	
	// Fermiamo gli interrupt
	video_puts("\n\n");
	asm("cli");
	
	// Mandiamo il segnale di kill a tutti i processi
	/*DEBUGP("main.c -> killing all processes\n");
	video_puts_colored(VIDEO_HI_BLUE_BLACK, " -> ");
	video_puts("Killing all tasks\n");
	*/
	video_puts_colored(VIDEO_HI_BLUE_BLACK, " -> ");		
	video_puts("Power down.\n");
	
	// Fermiamo la cpu
	asm("hlt");
	
	while(1);
}
